<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <p>
    <a href="https://blog.csdn.net/weixin_34124939/article/details/91398764">转载：原文链接</a>
  </p>

<script type="text/javascript">

Function.prototype.myCall = function () {
    //获取this指向
    var _this = arguments[0];
    
    //兼容this指向为原始值
    if (typeof _this == 'number') {
        _this = new Number(_this)
    } else if (typeof _this == 'boolean') {
        _this = new Boolean(_this)
    } else if (typeof _this == 'string') {
        _this = new String(_this)
    } else if (!_this) {
        //兼容浏览器和node
        try {
            _this = window;
        } catch (e) {
            _this = {};
        }
    }
    
    // 获取参数
    var _arguments = [...arguments].slice(1);
    //挂载到this指向上面
    _this.fn = this;
    //使用eval执行这个新增的方法
    var result = eval('_this.fn(' + [..._arguments].join(',') + ')');
    //删除该方法
    delete _this.fn;
    //返回执行结果
    return result;
}


Function.prototype.myApply = function (_this, arr) {
 
    _this = _this;
    
    if (typeof _this == 'number') {
        _this = new Number(_this)
    } else if (typeof _this == 'boolean') {
        _this = new Boolean(_this)
    } else if (typeof _this == 'string') {
        _this = new String(_this)
    } else if (!_this) {
        try {
            _this = window;
        } catch (e) {
            _this = {};
        }
    }
 
    _this.fn = this;
 
    if (!arr) {
        var result = ctx.fn();
    } else {
        var result = eval('_this.fn(' + [...arr].toString() + ')');
    }
    delete _this.fn;
        return result;
}


Function.prototype.myBind = function (target) {
    var self = this;
    //获取参数
    var args = [].slice.call(arguments, 1);
    var fn = function () {
        var _arg = [].slice.call(arguments, 0);
        return self.apply(target, args.concat(_arg));
    }
    // 设置返回的新函数的函数的原型链
    fn.prototype.__proto__ = this.prototype
    return fn;
}


//防抖：疯狂触发函数，只有第一次好使。
function debounce(fn, delay) {
   var lock = false;
   var timer = null;
   return function () {
       if (!lock) { //开锁状态下
           fn(...arguments);
           lock = true;
           timer = setTimeout(() => {
               lock = false;
           }, delay);
       } else { //锁启用状态下
           clearInterval(timer);
           timer = setTimeout(() => {
               lock = false;
           }, delay);
       }
   }
}

//节流：疯狂触发函数， 只有单位时间内好使一次。
function throttle(fn, delay) {
    var lock = false;
    return function () {
        if (!lock) {
            fn(...arguments);
            lock = true;
            setTimeout(() => {
                lock = false;
            }, delay);
        }

    }
}


//单层柯里化：传入想要进行柯里化处理的函数和前几个参数
function fixedParam(fn) {
    var _arguments1 = [].slice.call(arguments, 1);
    return function () {
        var _arguments2 = [...arguments];
        fn.apply(this, [..._arguments1, ..._arguments2]);
 
    }
}
 
function sum(a, b, c, d) {
    console.log(a + b + c + d);
}
// 
var currySum = fixedParam(sum, 1, 2);
//下次执行输入剩下的参数
currySum(3, 4);


//详解柯里化：https://www.jianshu.com/p/2975c25e4d71
//函数柯里化 及 apply、call和bind的异同：https://blog.csdn.net/abcwangruili/article/details/79387609

</script>
</body>
</html>